home *** CD-ROM | disk | FTP | other *** search
- -- card: 4791 from stack: in
- -- bmap block id: 5107
- -- flags: 4000
- -- background id: 2707
- -- name:
-
-
- -- part 1 (field)
- -- low flags: 01
- -- high flags: 2007
- -- rect: left=43 top=182 right=285 bottom=463
- -- title width / last selected line: 0
- -- icon id / first selected line: 0 / 0
- -- text alignment: 0
- -- font id: 3
- -- text size: 9
- -- style flags: 0
- -- line height: 12
- -- part name: code
-
-
- -- part 2 (button)
- -- low flags: 00
- -- high flags: A002
- -- rect: left=205 top=286 right=308 bottom=305
- -- title width / last selected line: 0
- -- icon id / first selected line: 0 / 0
- -- text alignment: 1
- -- font id: 3
- -- text size: 9
- -- style flags: 0
- -- line height: 12
- -- part name: Copy Source Code
- ----- HyperTalk script -----
- on mouseUp
- select text of cd fld "code"
- doMenu "Copy Text"
- select empty
- end mouseUp
-
-
-
- -- part contents for background part 1
- ----- text -----
- This init comes from Maurice Volaski, 29 Callodine Ave. Amherst, NY 14226-3125, 716-838-6663. Internet: volaski@contra.med.buffalo.edu.
- Below is the source code listing for the OneSpace init written in THINK C.
-
-
- -- part contents for card part 1
- ----- text -----
- Special thanks to Ken McLeod for answering questions regarding this code. Thanks also to Mark Pierce for doing such wonderful startup icons.
-
- /*=================================================================
- The following is the source code for the OneSpace INIT by
- Maurice Volaski (volaski@contra.med.buffalo.edu)
- prepared in THINK C.
-
- In typesetting it is a general rule to use one space character at a time.
- Thus, as a typesetting tool, the Macintosh differs from its earlier
- predecessors, especially the typewriter, where it is, for example, a
- general rule to type two spaces at the end of a sentence.
- The init’s purpose is to prevent users from typing more than one space in
- a row, especially by accident, thus preserving the standards of
- typesetting as well as the integrity of the Macintosh as a typesetting
- tool.
-
- To adhere to the user interface guidelines, the init can be switched
- on or off upon command. To toggle the init’s on/off setting use
- command-shift-spacebar.
-
- Complete conerning using this init are discussed in the user’s
- documentation.
-
- The following commented material concerning inits in general
- as well this one is from Ken McLeod:
-
-
- IMPORTANT: You should never write a patch which is a “tail”
- patch, since various system routines check the return address
- on the stack to see who called them (see technote #212). A
- “tail” patch is one which calls the original routine as a
- subroutine call, after which control returns to the patch code.
- A correctly-written patch jumps directly to the original routine
- after doing whatever it does; control doesn’t return to the patch
- code until the next time that trap is called.
-
- GetNextEvent is a special case, since a patch to GNE will
- usually need to alter the EventRecord AFTER it has been filled
- in by GNE, but before it gets back to the original caller.
- Apple has provided a documented method for doing this WITHOUT
- having to use a tail patch. The following is excerpted from
- technote #85:
-
- > You must call GetNextEvent periodically. GetNextEvent uses a
- > filter (GNE filter) which allows for a routine to be installed
- > which overrides (or augments) the behavior of the system. The
- > GNE filter is installed by pointing the low-memory global jGNEFilter
- > (a long word at $29A) to the routine. After all other GNE processing
- > is complete, the routine will be called with A1 pointing to the
- > event record and D0 containing the boolean result. The filter may
- > then modify the event record or change the function result by
- > altering the word on the stack at 4(A7). This word will match D0
- > initially, of course.
-
- At startup, our INIT simply installs a pointer to our ModifyEvent()
- function in the jGNEFilter low-memory global, saving the pointer
- it currently contains. When ModifyEvent() gets control, it alters
- the event record, then jumps to the saved jGNEFilter function, or
- returns if the saved pointer was nil.
-
- Note that patching GetNextEvent has no effect on desk accessories,
- since DA’s are drivers, and get their event records handed to them
- via the csParam field of a parameter block (in other words, they
- don’t call GetNextEvent.) Modification of events for drivers is
- somewhat more complex, and “outside the scope of this example.”
-
- Remember to set the “System Heap” and “Locked” bits for the
- INIT resource in the “Set Project Type...” dialog! Remember to
- check the <MacHeaders> option on in the Options dialog. Also, don’t
- forget to include MacTraps in your project!
-
- =================================================================*/
-
-
-
- #include <SetUpA4.h>/*SetUpA4.h generates inline code here, as well as 4 bytes of
- storage for A4 (storage for globals is at end of our code) */
-
- #define NIL 0L
- #define procID 0
- #define GetNextEventTrap 0xA970
-
- extern long jGNEFilter : 0x29A;/*low-memory global (Ptr) */
- long savedjGNEFilter;/*storage for old jGNEFilter ptr */
- EventRecord *theEvent;/*storage for ptr to EventRecord */
- short isValidEvent;/*storage for boolean result */
- int spaceCounter;/*storage for counting # of spaces typed */
- Boolean trapSpace;/*storage for turning INIT on or off */
-
- /*the following function will be called by GetNextEvent,
- so it must be declared as a pascal function, like just
- about everything else which can be called by the system! */
-
- pascal void ModifyEvent()
- {/* as per technote #85, A1 contains the EventRecord
- pointer and D0 contains the result GNE will return.
- We’ll have to save them before calling SetUpA4(), since
- that routine changes register A1, and we'll also need
- to restore them before leaving! */
- asm {
- move.l A1,-(sp);push event ptr from A1 onto stack
- move.w D0,-(sp);push event validity word from D0
- }
-
- /* now it’s safe to get our globals! */
-
- SetUpA4();
- /*get the values we saved. At this point, A4 (4 bytes) has
- been pushed on top of them by SetUpA4(), so we can’t just
- pop them off the stack here; however, we know their offsets
- from the current stack pointer (which has just been moved up
- by 4). */
- asm {
- move.w 4(sp),isValidEvent;get saved value from stack
- move.l 6(sp),theEvent;get saved pointer from stack
- }
- if (isValidEvent)
- /*This is where the init does its job. If the event is keydown or
- autokey and the character is a space, it increments the space
- counter by one. If the command and shift keys were held down
- with the space character, the init sets its on/off setting
- to the opposite of its current state and decrements the
- spaceCounter to 0. If the init is set on, it proceeds to check
- how many spaces have been typed. If one space has been typed, it
- decrements the space counter by one and alters the EventRecord
- to record a null event and alerts the user that more than
- one space is not allowed. Otherwise, if the character is not a
- space it sets the space counter to 0. */
-
- if ((theEvent->what == keyDown) ||(theEvent->what == autoKey)) {
- if ((theEvent->message & 0xFF) == ' ') {
- spaceCounter+=1;
- if ((theEvent->modifiers & shiftKey) !=0 && (theEvent->modifiers & cmdKey)) {
- trapSpace=!trapSpace;
- spaceCounter=0;
- }
- if (trapSpace) {
- if (spaceCounter==2) {
- theEvent->what=NIL;
- isValidEvent=false;
- spaceCounter=1;
- SysBeep(1);
- }
- }
- }
- else
- spaceCounter=0;
- }
- /*now decide how to return. If our saved jGNEFilter isn’t NIL, we
- need to jump to someone else’s jGNEFilter routine (unless, for
- some unforeseen reason, the saved routine is ModifyEvent, which
- would send us on a trip to recursion hell!). Otherwise, we’ll
- just return normally. Remember to restore A1 and D0 (we saved
- them on the stack...) */
- asm {
- move.l savedjGNEFilter,A0 ;put saved addr in A0
- move.l (sp)+,A4 ;RestoreA4 (undoes SetUpA4)
- ;(can’t access globals now...)
- move.w (sp)+,D0 ;get it off the stack first, put it back in D0
- move.l (sp)+,A1 ;get saved ER pointer off stack, too
- jmp (A0) ;jump to next filter routine
- }
- }
-
-
- /*main—once-only code that saves the pointer to us, sets
- up our static storage, and installs the patch. */
-
-
- /*this code calls the compiled CShowINIT */
- /*to load the various startup icons */
- void showIcon(iconID,move)
- int iconID;
- int move;
- {
- Handle procH;
-
- if ((procH = GetResource('PROC', procID)) != NIL){
- HLock(procH);
- CallPascal(iconID, move, *procH);
- HUnlock(procH);
- }
- }
-
- void main(){
- Handle myHandle;
- Ptr myPtr;
- long theTicks;
-
- asm {
- move.l A0, myPtr
- }
- RememberA0();
- SetUpA4();
- if (Button()) {
- showIcon(130,-1);/*show the icon to indicate that */
- /*init isn’t loading */
- }
- else {
- myHandle = RecoverHandle(myPtr); /*get handle to our rsrc */
- DetachResource(myHandle); /*so it won’t go away */
- HLock(myHandle); /*lock it down! */
- showIcon(128,0);/*show the startup icon */
- Delay(30,&theTicks);/*give a chance to see it */
- showIcon(129,-1);/*do animation icon */
- trapSpace=true;/*turn multiple space trapping on */
- spaceCounter=0;/*initialize the space counter— */
- /*no spaces have been typed. */
- savedjGNEFilter = jGNEFilter;/*save address of old jGNEFilter routine */
- jGNEFilter = (long) ModifyEvent;/*point jGNEFilter to our ModifyEvent function */
-
- }
- RestoreA4();
- }
-
-
- -- part contents for background part 4
- ----- text -----
- 4 of 4